<?php
class Mozg_Detector implements Iterator
{
	protected $_components = array();
	protected $_pos = 0;
	protected $_masterObj;
	protected $_parent;
	
    public function __construct($obj, Mozg_Detector $parent = null)
    {
    	$this->_masterObj = $obj;
    	$this->_parent = $parent;
    	$this->DetectComponents($obj);
    }

    /**
		собираем список всех родительских классов
     */
    protected function DetectComponents($obj)
    {
    	$currentClass = get_class($obj);

    	$checkContext = $this->_parent instanceof self;
    	
    	do
    	{
    		if (preg_match('#^App_(?:Module_([^_]+)_){0,1}(?:Component_([^_]+)_){0,1}#is', $currentClass, $matches))
    		{
    			if ($checkContext)
    			{
    				$parentContext = $this->_parent->last();
	    			if (
	    				(!strlen($matches[2]) && strlen($parentContext[1])) //объект не в контексте компонента, родитель в контексте компонента
						|| (!strlen($matches[1]) && strlen($parentContext[0])) //объект не в контексте модуля, родитель в контексте модуля
	    			)
	    			{
	    				//т.к. объект не принадлежит никакому компоненту, то назначаем ему контекст родителя,
	    				//который или их содержит или вызывается напрямую мне компонента
	    				$this->_components = $this->_parent->GetComponents();
	    				return $this;
	    			}
	    			
	    			$checkContext = false;
    			}
    			
    			$matches = array_map('strtolower', $matches);
    			$this->_components[$matches[1]. '::' .$matches[2]] = array($matches[1], $matches[2]);
    		}
    	}
    	while ($currentClass = get_parent_class($currentClass));

    	$this->_components = array_values($this->_components);
    	
    	$first = $this->first();
    	if ($first[1]) $this->_components[] = array($first[0], null);

    	$first = $this->first();
    	if ($first[0]) $this->_components[] = array(null, null);
    	
    	return $this;
    }

    public function GetComponents()
    {
    	return $this->_components;
    }
    
    public function last()
    {
    	return $this->_components[0];
    }
    
    public function first()
    {
    	return $this->_components[sizeof($this->_components) - 1];
    }

    public function rewind()
    {
        $this->_pos = 0;
    }

    public function current()
    {
        return $this->_components[$this->_pos];
    }

    public function key()
    {
        return $this->_pos;
    }

    public function next()
    {
        ++$this->_pos;
    }

    public function valid()
    {
        return isset($this->_components[$this->_pos]);
    }
    
}